#!/bin/sh /etc/rc.common
# Copyright (C) 2018-2024 X-WRT

START=95

IPOPS="lua /usr/lib/lua/ipops.lua"
test -e /usr/share/natflow/ipops.lua && IPOPS="lua /usr/share/natflow/ipops.lua"

stop()
{
	test -c /dev/hostacl_ctl || return 0
	echo clear >/dev/hostacl_ctl
	for i in $(seq 0 31); do
		ipset destroy host_acl_rule${i}_mac 2>/dev/null
		ipset destroy host_acl_rule${i}_ipv4 2>/dev/null
		ipset destroy host_acl_rule${i}_ipv6 2>/dev/null
	done
}

# ipset_add ipsetname net
ipv4set_add()
{
	local ipsetname=$1
	local net=$2
	#hack for 0.0.0.0/0
	[ "$net" = "0.0.0.0/0" ] && net="0.0.0.0/1 128.0.0.0/1"
	for n in $net; do
		ipset add $ipsetname $n
	done
}

# ipset_add ipsetname net
ipv6set_add()
{
	local ipsetname=$1
	local net=$2
	#hack for ::/0
	[ "$net" = "::/0" ] && net="::/1 8000::/1"
	for n in $net; do
		ipset add $ipsetname $n
	done
}

start()
{
	test -c /dev/hostacl_ctl || return 0
	stop
	enabled=$(uci get hostacl.@main[0].enabled 2>/dev/null || echo 0)
	[ $enabled = "0" ] && return 0

	idx=0
	while uci get hostacl.@rule[$idx] &>/dev/null; do
		disabled=$(uci get hostacl.@rule[$idx].disabled 2>/dev/null || echo 0)
		if [ "$disabled" = "1" ]; then
			idx=$((idx+1))
			continue
		fi

		ip=$(uci get hostacl.@rule[$idx].ip 2>/dev/null)
		ip=$($IPOPS netStrings2ipcidrStrings "$ip")
		if [ "$(echo $ip | sed 's/,/ /g' | wc -w)" -ge 1 ]; then
			ipset create host_acl_rule${idx}_ipv4 hash:net family inet 2>/dev/null
			ipset flush host_acl_rule${idx}_ipv4
			for net in $(echo $ip | sed 's/,/ /g'); do
				ipv4set_add host_acl_rule${idx}_ipv4 $net
			done
		fi

		ipv6=$(uci get hostacl.@rule[$idx].ipv6 2>/dev/null)
		if test -n "$ipv6"; then
			ipset create host_acl_rule${idx}_ipv6 hash:net family inet6 2>/dev/null
			ipset flush host_acl_rule${idx}_ipv6
			for net in $(echo $ipv6 | sed "s/,/ /g;s/'/ /g"); do
				ipv6set_add host_acl_rule${idx}_ipv6 $net
			done
		fi

		mac=$(uci get hostacl.@rule[$idx].mac 2>/dev/null)
		if test -n "$mac"; then
			ipset create host_acl_rule${idx}_mac hash:mac 2>/dev/null
			ipset flush host_acl_rule${idx}_mac
			for net in $(echo $mac | sed "s/,/ /g;s/'/ /g"); do
				ipset add host_acl_rule${idx}_mac $net
			done
		fi

		action=$(uci get hostacl.@rule[$idx].action 2>/dev/null)
		if [ "$action" = "record" ]; then
			action=0
		elif [ "$action" = "drop" ]; then
			action=1
		elif [ "$action" = "reset" ]; then
			action=2
		elif [ "$action" = "redirect" ]; then
			action=3
		else
			action=0
		fi

		host=$(uci get hostacl.@rule[$idx].host 2>/dev/null | tr A-Z a-z)
		host=$(echo $host | sed "s/,/ /g;s/'/ /g")
		for HOST in $host; do
			echo add acl=${idx},${action},$HOST >/dev/hostacl_ctl
		done

		idx=$((idx+1))
	done
}

restart()
{
	start
}
